namespace Skymate.Commands
{
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Dynamic;

    using Skymate.Lyjt.Core;

    /// <summary>
    /// 配时方案
    /// </summary>
    public class TimingPlan
    {
        public const int BufferSize = 24;

        public TimingPlan()
        {
            this.TimingPlanPhases = new List<TimingPlanPhase>();
        }

        /// <summary>
        /// 方案好
        /// </summary>
        public int No { get; set; }

        /// <summary>
        /// 协调相位号
        /// </summary>
        public int CoordinatePhase { get; set; }

        /// <summary>
        /// 协调相位差
        /// </summary>
        public int PhaseDifference { get; set; }

        /// <summary>
        /// 方案相位
        /// </summary>
        public List<TimingPlanPhase> TimingPlanPhases { get; set; }

        public int Checksum { get; set; }

        public static TimingPlan Create(byte[] buffer)
        {
            if (DynamicQueryable.Count(buffer) != BufferSize)
            {
                return null;
            }

            var result = new TimingPlan();

            result.No = buffer[0];
            result.CoordinatePhase = buffer[1];
            result.PhaseDifference = buffer[2];

            for (var i = 0; i < 10; i++)
            {
                var phaseBuff = new[] { buffer[3 + (i * 2)], buffer[4 + (i * 2)] };
                result.TimingPlanPhases[0] = TimingPlanPhase.Create(phaseBuff);
            }

            result.Checksum = buffer[23];

            return result;
        }

        public string[] ToStrings()
        {
            IList<string> result = new List<string>();

            result.Add(this.No.ToString());
            result.Add(this.CoordinatePhase.ToString());
            result.Add(this.PhaseDifference.ToString());

            return result.ToArray();
        }

        public byte[] ToBytes()
        {
            var result = new byte[BufferSize];
            result[0] = (byte)this.No;
            result[1] = (byte)this.CoordinatePhase;
            result[2] = (byte)this.PhaseDifference;

            if (this.TimingPlanPhases.Count < 10)
            {
                for (var i = this.TimingPlanPhases.Count; i < 10; i++)
                {
                    this.TimingPlanPhases.Add(new TimingPlanPhase());
                }
            }

            for (var i = 0; i < this.TimingPlanPhases.Count; i++)
            {
                var planPhase = this.TimingPlanPhases[i];
                var buffer = planPhase.ToBytes();
                result[3 + (i * 2)] = buffer[0];
                result[4 + (i * 2)] = buffer[1];
            }

            result[23] = this.GetChecksum(result.Range(0, BufferSize - 1));

            return result;
        }

        private byte GetChecksum(byte[] buffer)
        {
            return buffer.Aggregate<byte, byte>(0x00, (current, b) => (byte)(current + b));
        }
    }
}